npx create-react-app my-app --template redux
// npm
npm i react-redux @reduxjs/toolkit
// yarn
yarn add react-redux @reduxjs/toolkit
可依自己的需求安裝環境
使用 Redux Toolkit,你會聽到幾個關鍵字:
store
:用來存放資料狀態reducer
:用來放改變 state 狀態的方法action
:reducer 要修改 state 的話,需要傳入 action ,去判斷要啟動哪個 reducer,藉由 dispatch
呼叫方法Provider
:在所有組件的最外面包一層 Provider,傳入 store,所有被包覆的組件都可以使用到 store 的狀態。slice
:存放 state、reducer、action 的檔案Store
Provider
,並傳入 store,使整個組件都能使用 store 資料Slice
,設定 state、reducer、action製作一個 todoList 列表,輸入框輸入文字,點擊按鈕後新增行程
store/index.js
import { configureStore } from "@reduxjs/toolkit";
import todoReducer from "./slice/todo";
export default configureStore({
reducer: {
todo: todoReducer,
},
});
將 slice 新增在 reducer
configureStore
:創建 store 的參數,原生為 creactStore,使用 creactStore 時會有被棄用的警告
import { configureStore } from "@reduxjs/toolkit";
import todoReducer from "./slice/todo";
import productReducer from "./slice/product";
export default configureStore({
reducer: {
todo: todoReducer,
product: productReducer
},
});
如有多個檔案,一樣 import 進來,新增在 reducer
src/App.js
import { Provider } from "react-redux";
import store from "./store/index";
import Todo from "./Todo";
export default function App() {
return (
<Provider store={store}>
<Todo />
</Provider>
);
}
載入 Provider
與 store
,Provider 組件傳入 store
包在 Provider 裡的組件都可以使用 store
store/slice/todo.js
import { createSlice } from "@reduxjs/toolkit";
export const todoSlice = createSlice({
name: "todo",
initialState: {
todolist: [
{ id: 1, name: "起床" },
{ id: 2, name: "刷牙洗臉" },
{ id: 3, name: "吃早餐" },
{ id: 4, name: "上班" }
]
},
reducers: {
addTodo: (state, action) => {
state.todolist.push(action.payload);
}
}
});
export const { addTodo } = todoSlice.actions; // 取用方法
export const selectTodo = (state) => state.todo; // 取用資料
export default todoSlice.reducer;
createSlice
:創建 slice,把 Redux 原生的 state、reducer、action 都合在一包,稱之為 slice
name
:取一個相關的名稱
initialState
:所有狀態的初始值
reducers
:存放函式,傳入兩個參數,第一個為需要修改的 state,第二個為 action 讓你傳入的參數,用來改變 state
components/TodoList.js
import { useSelector } from "react-redux";
import { selectTodo } from "../store/slice/todo";
const TodoList = () => {
const states = useSelector(selectTodo);
return (
<ul>
{states.todolist.map((i) => (
<li key={i.id}>{i.name}</li>
))}
</ul>
);
};
export default TodoList;
將預設行程渲染出來
useSelector
:拿取 store 的 state,傳入在 slice 建立的 selectTodo
src/Todo.js
import { useDispatch } from "react-redux";
import TodoList from "./components/TodoList";
import { addTodo } from "./store/slice/todo";
import { useState } from "react";
export default function Todo() {
const [text, setText] = useState("");
const changeText = (e) => {
setText(e.target.value);
};
const dispatch = useDispatch();
const handleAddTodo = () => {
dispatch(addTodo({ id: new Date().getTime(), name: text }));
};
return (
<div>
<input
type="text"
value={text}
onChange={changeText}
/>
<TodoList />
<button onClick={handleAddTodo}>
新增行程
</button>
</div>
);
}
建立輸入框,按鈕新增行程,將 id、輸入文字傳入 addTodo
useDispatch
:需藉由 useDispatch 使用 store 裡的 actions,傳入在 slice 建立的 addTodo()
打開 codesandbox 程式碼範例 一起玩看看吧!
Redux Toolkit 真的比 Redux 好懂很多,真是感謝 Redux Toolkit 的出現
如果專案滿大的話,滿推薦使用 Redux Toolkit 來管理狀態資料,
學會了基本的 store 使用,明天繼續來講怎麼用 Redux Toolkit 操作非同步吧!
本文將同步更新至我的部落格
Lala 的前端大補帖